#ifndef METADATAIO_H
#define METADATAIO_H
#include <string>
#include <vector>
#include <map>
#include <algorithm>
#include "ErrorCode.h"
#include "StoreObject.h"
#include "MetaObject.h"
//#include "rados/librados.hpp"
//#include "etcd/v3/Transaction.hpp"
#include "Client.hpp"

using namespace std;

namespace gitstore {
struct Node;
struct Object;
struct Branch;
class CObjectCodeTransBase;

class CMetaDataIOBase {
protected:
    CMetaDataIOBase();
    virtual ~CMetaDataIOBase() {}
//public:
//    virtual ErrorStatus begin(const string& obj_name) = 0;
//    virtual ErrorStatus commit(const string& obj_name) = 0;
//    virtual ErrorStatus rollback(const string& obj_name) = 0;

public:
    virtual ErrorStatus createNode(const Node& node, int& revision) = 0;
    virtual ErrorStatus loadNode(const string& obj_name, const string& version, Node& node, int& revision) = 0;
    virtual ErrorStatus saveNode(const Node& node, int revision) = 0;

    virtual ErrorStatus createBranch(const Branch& branch, int& revision) = 0;
    virtual ErrorStatus loadBranch(const string& obj_name, const string& br_name, Branch& branch_info, int& revision) = 0;
    virtual ErrorStatus saveBranch(const Branch& branch, int revision, int& revision_new) = 0;

    virtual ErrorStatus createObject(const Object& object, int& revision) = 0;
    virtual ErrorStatus loadObject(const string& obj_name, Object& dataset_info, int& revision) = 0;
    virtual ErrorStatus saveObject(const Object& object, int revision) = 0;

    virtual ErrorStatus listObject(vector<string>& objects) = 0;
    virtual ErrorStatus listBranches(const string& obj_name, vector<string>& branches) = 0;
    virtual ErrorStatus listNodes(const string& obj_name, vector<string>& nodes) = 0;
protected:
    std::shared_ptr<CObjectCodeTransBase> _trans_op;
};

//class CMockMetaDataIO:public CMetaDataIOBase {
//public:
//    CMockMetaDataIO();
//    ~CMockMetaDataIO() override;
//private:
//    std::map<std::string, std::map<std::string, std::string>> _meta_store;
//public:
//    virtual ErrorStatus begin(const string& obj_name) override;
//    virtual ErrorStatus commit(const string& obj_name) override;
//    virtual ErrorStatus rollback(const string& obj_name) override;
//public:
//    virtual ErrorStatus loadNode(const string& obj_name, const string& version, Node& node) override;
//    virtual ErrorStatus saveNode(const Node& node) override;

//    virtual ErrorStatus loadBranch(const string& obj_name, const string& br_name, Branch& branch) override;

//    virtual ErrorStatus saveBranch(const Branch& branch) override;

//    virtual ErrorStatus loadObject(const string& obj_name, Object& dataset) override;

//    virtual ErrorStatus saveObject(const Object& object) override;

//    virtual ErrorStatus listObject(vector<string>& objects) override;
//private:
//    ErrorStatus encodeObject(const Object& object, std::string &json_string);
//    ErrorStatus decodeObject(Object& object, const std::string &json_string);
//    ErrorStatus encodeBranch(const Branch& branch, std::string &json_string);
//    ErrorStatus decodeBranch(Branch& branch, const std::string &json_string);
//    ErrorStatus encodeNode(const Node& node, std::string &json_string);
//    ErrorStatus decodeNode(Node& node, const std::string &json_string);
//};

class CEtcdMetaDataIO : public CMetaDataIOBase {
public:
    CEtcdMetaDataIO(const std::string& url, AppMode mode = AppMode::Single);
    ~CEtcdMetaDataIO() override;
private:
    etcd::Client _etcd_client;
//    etcdv3::Transaction _etcd_txn;
//public:
//    virtual ErrorStatus begin(const string& obj_name) override;
//    virtual ErrorStatus commit(const string& obj_name) override;
//    virtual ErrorStatus rollback(const string& obj_name) override;

public:
    virtual ErrorStatus createNode(const Node& node, int& revision) override;
    virtual ErrorStatus loadNode(const string& obj_name, const string& version, Node& node, int& revision) override;
    virtual ErrorStatus saveNode(const Node& node, int revision) override;

    virtual ErrorStatus createBranch(const Branch& branch, int& revision) override;
    virtual ErrorStatus loadBranch(const string& obj_name, const string& br_name, Branch& branch, int& revision) override;
    virtual ErrorStatus saveBranch(const Branch& branch, int revision, int& revision_new) override;

    virtual ErrorStatus createObject(const Object& object, int& revision) override;
    virtual ErrorStatus loadObject(const string& obj_name, Object& dataset, int& revision) override;
    virtual ErrorStatus saveObject(const Object& object, int revision) override;

    virtual ErrorStatus listObject(vector<string>& objects) override;
    virtual ErrorStatus listBranches(const string& obj_name, vector<string>& branches) override;
    virtual ErrorStatus listNodes(const string& obj_name, vector<string>& nodes) override;

    private:
    std::string obj_path;
};

//class CCephMetaDataIO : public CMetaDataIOBase {
//public:
//    CCephMetaDataIO(const std::string& cluster_name, const std::string& user_name, const std::string& config_file_path, const std::string& pool_name);
//    ~CCephMetaDataIO() override;
//private:
//    librados::Rados _cluster;
//    librados::IoCtx _io_ctx;
//public:
//    virtual ErrorStatus begin(const string& obj_name) override;
//    virtual ErrorStatus commit(const string& obj_name) override;
//    virtual ErrorStatus rollback(const string& obj_name) override;
//public:
//    virtual ErrorStatus loadNode(const string& obj_name, const string& version, Node& node) override;
//    virtual ErrorStatus saveNode(const Node& node) override;
//    virtual ErrorStatus loadBranch(const string& obj_name, const string& br_name, Branch& branch) override;
//    virtual ErrorStatus saveBranch(const Branch& branch) override;
//    virtual ErrorStatus loadObject(const string& obj_name, Object& dataset) override;
//    virtual ErrorStatus saveObject(const Object& object) override;
//    virtual ErrorStatus listObject(vector<string>& objects) override;

//    ErrorStatus encodeObject(const Object& object, std::string &json_string);
//    ErrorStatus decodeObject(Object& object, const std::string &json_string);
//    ErrorStatus encodeBranch(const Branch& branch, std::string &json_string);
//    ErrorStatus decodeBranch(Branch& branch, const std::string &json_string);
//    ErrorStatus encodeNode(const Node& node, std::string &json_string);
//    ErrorStatus decodeNode(Node& node, const std::string &json_string);
//};


}
#endif
